package cn.admin.config.common.protocol;

public final class VersionElement implements ProtocolElement,Comparable<VersionElement> {

    public short major;
    public short minor;
    public int build;
    public static final VersionElement CURRENT = new VersionElement(1,2,0);
    private static final long serialVersionUID = 1L;

    public VersionElement(int major,int minor,int build) {
        this.set(major,minor,build);
    }

    public void set(int major,int minor,int build) {
        this.major = (short) major;
        this.minor = (short) minor;
        this.build = build;
    }

    public void set(VersionElement element) {
        this.set(element.major,element.minor,element.build);
    }

    public boolean isSupported() {
        return CURRENT.equals(this);
    }

    public boolean isSupported(VersionElement minVersion, VersionElement maxVersion) {
        long version = this.toLong();
        return version >= minVersion.toLong() && version <= minVersion.toLong();
    }

    public boolean isSupported(SinceVersion since) {
        return this.major >= since.major() &&
                this.minor >= since.minor() && this.build >= since.build();
    }

    @Override
    public ProtocolElementUid uid() {
        return ProtocolElementUid.ELEMENT_VERSION;
    }

    @Override
    public int compareTo(VersionElement that) {
        if (this.major > that.major) {
            return 1;
        } else if (this.major < that.major) {
            return -1;
        } else if (this.minor > that.minor) {
            return 1;
        } else if (this.minor < that.minor) {
            return -1;
        } else if (this.build > that.build) {
            return 1;
        } else {
            return this.build < that.build ? -1 : 0;
        }
    }

    @Override
    public int hashCode() {
        int result = 1;
        result = 31 * result + this.build;
        result = 31 * result + this.major;
        result = 31 * result + this.minor;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        } else if (obj == null) {
            return false;
        } else if (this.getClass() != obj.getClass()) {
            return false;
        } else {
            VersionElement other = (VersionElement)obj;
            if (this.build != other.build) {
                return false;
            } else if (this.major != other.major) {
                return false;
            } else {
                return this.minor == other.minor;
            }
        }
    }

    private long toLong() {
        return (long)(this.major << 48 + this.minor << 32 + this.build);
    }
}
